<!DOCTYPE html>
<html>
<head>
    <title>Mass-Spring System Diagram</title>
</head>
<body>
    <canvas id="physicsCanvas" width="500" height="450"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // Clear canvas with a white background
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Set drawing properties
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 2;
        ctx.font = '20px Arial';
        ctx.textAlign = 'center';

        // --- Define coordinates and dimensions ---
        const supportY = 60;
        const supportX1 = 100;
        const supportX2 = 400;
        const springCenterX = 250;
        const springTopY = supportY;
        const springWireTopLength = 20;
        const springCoilTopY = springTopY + springWireTopLength;
        const springCoilHeight = 160;
        const springCoilBottomY = springCoilTopY + springCoilHeight;
        const springWireBottomLength = 20;
        const springBottomY = springCoilBottomY + springWireBottomLength;
        const springRadius = 25;
        const numCoils = 9;

        const massWidth = 100;
        const massHeight = 50;
        const massTopY = springBottomY;
        const massLeftX = springCenterX - massWidth / 2;
        const massBottomY = massTopY + massHeight;

        const dimLineX = 380;

        // --- Drawing Functions ---

        // 1. Draw the fixed support
        function drawSupport() {
            ctx.beginPath();
            ctx.moveTo(supportX1, supportY);
            ctx.lineTo(supportX2, supportY);
            ctx.stroke();

            // Draw hatches
            const hatchLength = 15;
            const hatchSpacing = 25;
            ctx.lineWidth = 1.5;
            for (let x = supportX1; x <= supportX2; x += hatchSpacing) {
                ctx.beginPath();
                ctx.moveTo(x, supportY);
                ctx.lineTo(x - hatchLength, supportY - hatchLength);
                ctx.stroke();
            }
            ctx.lineWidth = 2; // Reset line width
        }

        // 2. Draw the spring
        function drawSpring() {
            ctx.beginPath();
            // Top straight wire
            ctx.moveTo(springCenterX, springTopY);
            ctx.lineTo(springCenterX, springCoilTopY);

            // Helical part
            const numPoints = numCoils * 20; // 20 points per coil for smoothness
            for (let i = 0; i <= numPoints; i++) {
                const y = springCoilTopY + (i / numPoints) * springCoilHeight;
                const angle = (i / numPoints) * numCoils * 2 * Math.PI;
                const x = springCenterX + springRadius * Math.cos(angle);
                ctx.lineTo(x, y);
            }
            
            // Connect to bottom straight wire
            ctx.lineTo(springCenterX, springCoilBottomY);
            ctx.lineTo(springCenterX, springBottomY);
            ctx.stroke();
        }

        // 3. Draw the mass
        function drawMass() {
            ctx.beginPath();
            ctx.rect(massLeftX, massTopY, massWidth, massHeight);
            ctx.stroke();
        }

        // 4. Draw labels and pointers
        function drawLabels() {
            ctx.textAlign = 'left';
            ctx.font = '22px sans-serif';

            // "spring" label
            ctx.fillText('spring', 80, 175);
            ctx.beginPath();
            ctx.moveTo(145, 172);
            ctx.lineTo(225, 168); // Point to a coil on the left
            ctx.stroke();

            // "mass M" label
            ctx.fillText('mass M', 80, 305);
            ctx.beginPath();
            ctx.moveTo(155, 302);
            ctx.lineTo(massLeftX, 300); // Point to the left side of the mass
            ctx.stroke();
        }

        // 5. Draw the length dimension 'L'
        function drawDimensionL() {
            // Main vertical line
            ctx.beginPath();
            ctx.moveTo(dimLineX, supportY);
            ctx.lineTo(dimLineX, massBottomY);
            ctx.stroke();

            // Arrowheads
            const arrowSize = 8;
            // Top arrowhead
            ctx.beginPath();
            ctx.moveTo(dimLineX - arrowSize / 2, supportY + arrowSize);
            ctx.lineTo(dimLineX, supportY);
            ctx.lineTo(dimLineX + arrowSize / 2, supportY + arrowSize);
            ctx.stroke();
            // Bottom arrowhead
            ctx.beginPath();
            ctx.moveTo(dimLineX - arrowSize / 2, massBottomY - arrowSize);
            ctx.lineTo(dimLineX, massBottomY);
            ctx.lineTo(dimLineX + arrowSize / 2, massBottomY - arrowSize);
            ctx.stroke();
            
            // Horizontal extension lines
            // Top line (solid)
            ctx.beginPath();
            ctx.moveTo(supportX2, supportY);
            //ctx.lineTo(dimLineX, supportY); // This is implied by the arrow placement
            ctx.stroke();
            
            // Bottom line (dashed)
            ctx.beginPath();
            ctx.setLineDash([5, 4]);
            ctx.moveTo(massLeftX + massWidth, massBottomY);
            ctx.lineTo(dimLineX, massBottomY);
            ctx.stroke();
            ctx.setLineDash([]); // Reset to solid line

            // 'L' label
            ctx.textAlign = 'left';
            ctx.font = 'italic 24px "Times New Roman"';
            ctx.fillText('L', dimLineX + 15, (supportY + massBottomY) / 2 + 8);
        }

        // 6. Draw the figure caption
        function drawCaption() {
            ctx.textAlign = 'center';
            ctx.font = 'bold 20px sans-serif';
            ctx.fillText('Fig. 3.1', canvas.width / 2, 420);
        }

        // --- Execute drawing ---
        drawSupport();
        drawSpring();
        drawMass();
        drawLabels();
        drawDimensionL();
        drawCaption();

    </script>
</body>
</html>